package logic

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"mall/common/cachex"
	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/moneyx"
	"mall/common/mqueuex"
	"mall/common/resultx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/logic/types"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/types/forum"
	"mall/service/user/rpc/userclient"

	"github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type RefreshCacheLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewRefreshCacheLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshCacheLogic {
	return &RefreshCacheLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *RefreshCacheLogic) RefreshCache(in *forum.RefreshCacheReq) (*forum.RefreshCacheResp, error) {
	if in.UserId == nil || *in.UserId == 0 {
		return nil, resultx.StatusError(resultx.USER_ID_REQUIRED, "")
	}

	if in.Type == nil || *in.Type == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	if in.PlatformId == nil || *in.PlatformId == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	var cacheType uint32 = *in.Type
	var meta []*forum.MetaInfo
	if cacheType >= cachex.ForumNewCollectEntry {
		newMeta, err := l.refreshCollectEntryCache(in)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshCollectEntryCache err: %+v", err))
		} else {
			meta = append(meta, newMeta...)
		}
		cacheType -= cachex.ForumNewCollectEntry
	}

	if cacheType >= cachex.ForumNewAnsweredQuestion {
		newMeta, err := l.refreshAnsweredQuestionCache(in)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshAnsweredQuestionCache err: %+v", err))
		} else {
			meta = append(meta, newMeta...)
		}
		cacheType -= cachex.ForumNewAnsweredQuestion
	}

	if cacheType >= cachex.ForumNewAskedQuestion {
		newMeta, err := l.refreshAskedQuestionCache(in)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshAskedQuestionCache err: %+v", err))
		} else {
			meta = append(meta, newMeta...)
		}
		cacheType -= cachex.ForumNewAskedQuestion
	}
	if cacheType >= cachex.ForumNewPhotoPost {
		newMeta, err := l.refreshPhotoCache(in)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshPhotoCache err: %+v", err))
		} else {
			meta = append(meta, newMeta...)
		}
		cacheType -= cachex.ForumNewPhotoPost
	}
	if cacheType >= cachex.ForumNewReview {
		newMeta, err := l.refreshReviewCache(in)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshReviewCache err: %+v", err))
		} else {
			meta = append(meta, newMeta...)
		}
	}

	return &forum.RefreshCacheResp{
		Meta: meta,
	}, nil
}

func (l *RefreshCacheLogic) refreshCollectEntryCache(in *forum.RefreshCacheReq) (meta []*forum.MetaInfo, err error) {
	userId := *in.UserId
	filterMap := make(map[string]map[string][]any)
	filterMap[model.ForumUserCollectColumns.UserID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.ForumUserCollectColumns.PlatformID] = map[string][]any{
		"equalTo": {*in.PlatformId},
	}
	filterMap[model.ForumUserCollectColumns.Status] = map[string][]any{
		"equalTo": {globalkey.StatusEnabled},
	}

	selectCols := []string{
		model.ForumUserCollectColumns.CollectID,
		model.ForumUserCollectColumns.ObjectID,
		model.ForumUserCollectColumns.ObjectType,
		model.ForumUserCollectColumns.SorterValue2,
	}
	list, _, err := l.svcCtx.ForumUser.GetCollects(l.ctx, model.M{
		"pageSize": int64(9),
		"orderBy":  model.ForumUserCollectColumns.CollectID + " DESC",
		"select":   strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	if len(list) > 0 {
		var pids []string
		for _, v := range list {
			if v.ObjectID > 0 && v.ObjectType == uint16(globalkey.PostTypeKnowledgeBase) {
				pids = append(pids, strconv.FormatInt(int64(v.ObjectID), 10))
			}
		}

		if len(pids) > 0 {
			perfumeMap, err := l.getPerfumeMap(pids)
			if err != nil {
				return nil, err
			}

			var entries []*types.KbEntryInfo
			if perfumeMap != nil {
				for _, v := range list {
					if parent, ok := perfumeMap[v.ObjectID]; ok {
						if v.SorterValue2.Valid {
							parent.Year = pointy.GetPointer(v.SorterValue2.String)
						}
						entries = append(entries, parent)
					}
				}
			}

			collectEntryItems, err := json.Marshal(entries)
			if err != nil {
				logrus.Info(fmt.Sprintf("RefreshCache refreshCollectEntryCache json.Marshal err: %+v", err))
				return nil, err
			}

			var userMeta []*userclient.UserMetaInfo
			userMeta = append(userMeta, &userclient.UserMetaInfo{
				Key:   pointy.GetPointer(mqueuex.UserStatisticCollectEntryNew), // "_collect_entry_status"
				Value: pointy.GetPointer("1"),
			})
			userMeta = append(userMeta, &userclient.UserMetaInfo{
				Key:   pointy.GetPointer(mqueuex.UserCacheCollectEntry), // "_collect_entry_items"
				Value: pointy.GetPointer(string(collectEntryItems)),
			})
			_, err = l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
				UserId:   pointy.GetPointer(userId),
				UserMeta: userMeta,
			})
			if err != nil {
				logrus.Info(fmt.Sprintf("RefreshCache refreshCollectEntryCache UserRpc.SetUserMeta err: %+v", err))
				return nil, err
			}

			meta = append(meta, &forum.MetaInfo{
				Id:    pointy.GetPointer(userId),
				Key:   pointy.GetPointer("collectEntryItems"),
				Value: pointy.GetPointer(string(collectEntryItems)),
			})
		}
	}

	return
}

func (l *RefreshCacheLogic) refreshAnsweredQuestionCache(in *forum.RefreshCacheReq) (meta []*forum.MetaInfo, err error) {
	userId := *in.UserId
	filterMap := make(map[string]map[string][]any)
	filterMap[model.ForumPostColumns.PostAuthorID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.ForumPostColumns.ForumID] = map[string][]any{
		"moreThanOrEqualTo": {l.svcCtx.Config.Query.DefaultForumId},
	}
	filterMap[model.ForumPostColumns.PostStatus] = map[string][]any{
		"notEqualTo": {globalkey.StatusDeleted},
	}
	selectCols := []string{
		model.ForumPostColumns.PostID,
		model.ForumPostColumns.TopicID,
		model.ForumPostColumns.PostContent,
		model.ForumPostColumns.PostDate,
		model.ForumPostColumns.PostStatus,
	}
	replyList, _, err := l.svcCtx.ForumPost.GetList(l.ctx, model.M{
		"pageSize": int64(3),
		"orderBy":  model.ForumPostColumns.PostModifiedDate + " DESC",
		"select":   strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	if len(replyList) > 0 {
		var tids []any // []model.ForumTopic.TopicID
		for _, v := range replyList {
			tids = append(tids, v.TopicID)
		}

		topicFilterMap := make(map[string]map[string][]any)
		topicFilterMap[model.ForumTopicColumns.TopicID] = map[string][]any{
			"in": tids,
		}
		topicFilterMap[model.ForumTopicColumns.ForumID] = map[string][]any{
			"moreThanOrEqualTo": {l.svcCtx.Config.Query.DefaultForumId},
		}
		topicFilterMap[model.ForumTopicColumns.TopicStatus] = map[string][]any{
			"equalTo": {globalkey.StatusApproved},
		}
		topicSelectCols := []string{
			model.ForumTopicColumns.TopicID,
			model.ForumTopicColumns.TopicAuthorID,
			model.ForumTopicColumns.Title,
			model.ForumTopicColumns.Slug,
		}
		topicList, _, err := l.svcCtx.ForumTopic.GetList(l.ctx, model.M{
			"select": strings.Join(topicSelectCols, ","),
		}, -1, topicFilterMap)
		if err != nil {
			return nil, err
		}

		idTopicMap := make(map[uint64]*model.ForumTopic)
		if len(topicList) > 0 {
			for _, v := range topicList {
				idTopicMap[v.TopicID] = v
			}
		}

		metaFilterMap := make(map[string]map[string][]any)
		metaFilterMap[model.ForumTopicMetumColumns.TopicID] = map[string][]any{
			"in": tids,
		}
		metaFilterMap[model.ForumTopicMetumColumns.MetaKey] = map[string][]any{
			"equalTo": {"_reply_count"},
		}
		metaList, _, err := l.svcCtx.ForumTopic.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
		if err != nil {
			return nil, err
		}

		idCountMap := make(map[uint64]uint32)
		if len(metaList) > 0 {
			for _, v := range metaList {
				if len(v.MetaKey) > 0 && v.MetaValue.Valid {
					if i, err := strconv.ParseInt(v.MetaValue.String, 10, 32); err == nil {
						idCountMap[v.TopicID] = uint32(i)
					}
				}
			}
		}

		var replies []*types.ReplyInfo
		for _, v := range replyList {
			var topic *types.TopicInfo
			if tv, ok := idTopicMap[v.TopicID]; ok {
				var replyCount *uint32
				if cnt, ok := idCountMap[tv.TopicID]; ok {
					replyCount = pointy.GetPointer(cnt)
				}
				topic = &types.TopicInfo{
					Id:         pointy.GetPointer(tv.TopicID),
					Title:      pointy.GetPointer(tv.Title),
					Slug:       pointy.GetPointer(tv.Slug),
					ReplyCount: replyCount,
				}
			}
			replies = append(replies, &types.ReplyInfo{
				Id:          pointy.GetPointer(v.PostID),
				ContentHtml: pointy.GetPointer(v.PostContent),
				Status:      pointy.GetPointer(uint32(v.PostStatus)),
				StatusText:  pointy.GetPointer(types.GetStatusText(int32(v.PostStatus))),
				UpdatedAt:   pointy.GetPointer(modelx.FormatTime(v.PostDate, "")),
				Topic:       topic,
			})
		}

		answeredQuestionItems, err := json.Marshal(replies)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshAnsweredQuestionCache json.Marshal err: %+v", err))
			return nil, err
		}

		var userMeta []*userclient.UserMetaInfo
		userMeta = append(userMeta, &userclient.UserMetaInfo{
			Key:   pointy.GetPointer(mqueuex.UserStatisticForumAnswerNew), // "_answered_question_new_status"
			Value: pointy.GetPointer("1"),
		})
		userMeta = append(userMeta, &userclient.UserMetaInfo{
			Key:   pointy.GetPointer(mqueuex.UserCacheForumAnswer), // "_answered_question_items"
			Value: pointy.GetPointer(string(answeredQuestionItems)),
		})
		_, err = l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
			UserId:   pointy.GetPointer(uint64(userId)),
			UserMeta: userMeta,
		})
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshAnsweredQuestionCache UserRpc.SetUserMeta err: %+v", err))
			return nil, err
		}

		meta = append(meta, &forum.MetaInfo{
			Id:    pointy.GetPointer(userId),
			Key:   pointy.GetPointer("answeredQuestionItems"),
			Value: pointy.GetPointer(string(answeredQuestionItems)),
		})
	}

	return
}

func (l *RefreshCacheLogic) refreshAskedQuestionCache(in *forum.RefreshCacheReq) (meta []*forum.MetaInfo, err error) {
	userId := *in.UserId
	filterMap := make(map[string]map[string][]any)
	filterMap[model.ForumTopicColumns.TopicAuthorID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.ForumTopicColumns.ForumID] = map[string][]any{
		"moreThanOrEqualTo": {l.svcCtx.Config.Query.DefaultForumId},
	}
	filterMap[model.ForumTopicColumns.TopicStatus] = map[string][]any{
		"notEqualTo": {globalkey.StatusDeleted},
	}

	selectCols := []string{
		model.ForumTopicColumns.TopicID,
		model.ForumTopicColumns.Title,
		model.ForumTopicColumns.Slug,
		model.ForumTopicColumns.TopicDate,
		model.ForumTopicColumns.TopicStatus,
	}
	topicList, _, err := l.svcCtx.ForumTopic.GetList(l.ctx, model.M{
		"pageSize": int64(3),
		"orderBy":  model.ForumTopicColumns.TopicModifiedDate + " DESC",
		"select":   strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	if len(topicList) > 0 {
		var ids []any
		for _, v := range topicList {
			ids = append(ids, v.TopicID)
		}

		metaFilterMap := make(map[string]map[string][]any)
		metaFilterMap[model.ForumTopicMetumColumns.TopicID] = map[string][]any{
			"in": ids,
		}
		metaFilterMap[model.ForumTopicMetumColumns.MetaKey] = map[string][]any{
			"equalTo": {"_reply_count"},
		}
		metaList, _, err := l.svcCtx.ForumTopic.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
		if err != nil {
			return nil, err
		}

		idCountMap := make(map[uint64]uint32)
		if len(metaList) > 0 {
			for _, v := range metaList {
				if len(v.MetaKey) > 0 && v.MetaValue.Valid {
					if i, err := strconv.ParseInt(v.MetaValue.String, 10, 32); err == nil {
						idCountMap[v.TopicID] = uint32(i)
					}
				}
			}
		}

		var list []*types.TopicInfo
		for _, v := range topicList {
			var replyCount *uint32
			if cnt, exist := idCountMap[v.TopicID]; exist {
				replyCount = pointy.GetPointer(cnt)
			}
			list = append(list, &types.TopicInfo{
				Id:         pointy.GetPointer(v.TopicID),
				Title:      pointy.GetPointer(v.Title),
				Slug:       pointy.GetPointer(v.Slug),
				Status:     pointy.GetPointer(uint32(v.TopicStatus)),
				StatusText: pointy.GetPointer(types.GetStatusText(int32(v.TopicStatus))),
				UpdatedAt:  pointy.GetPointer(modelx.FormatTime(v.TopicDate, "")),
				ReplyCount: replyCount,
			})
		}

		askedQuestionItems, err := json.Marshal(list)
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshAskedQuestionCache json.Marshal err: %+v", err))
			return nil, err
		}

		var userMeta []*userclient.UserMetaInfo
		userMeta = append(userMeta, &userclient.UserMetaInfo{
			Key:   pointy.GetPointer(mqueuex.UserStatisticForumQuestionNew), // "_asked_question_new_status"
			Value: pointy.GetPointer("1"),
		})
		userMeta = append(userMeta, &userclient.UserMetaInfo{
			Key:   pointy.GetPointer(mqueuex.UserCacheForumQuestion), // "_asked_question_items"
			Value: pointy.GetPointer(string(askedQuestionItems)),
		})
		_, err = l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
			UserId:   pointy.GetPointer(uint64(userId)),
			UserMeta: userMeta,
		})
		if err != nil {
			logrus.Info(fmt.Sprintf("RefreshCache refreshAskedQuestionCache UserRpc.SetUserMeta err: %+v", err))
			return nil, err
		}

		meta = append(meta, &forum.MetaInfo{
			Id:    pointy.GetPointer(userId),
			Key:   pointy.GetPointer("askedQuestionItems"),
			Value: pointy.GetPointer(string(askedQuestionItems)),
		})
	}

	return
}

func (l *RefreshCacheLogic) refreshPhotoCache(in *forum.RefreshCacheReq) (meta []*forum.MetaInfo, err error) {
	userId := *in.UserId
	filterMap := make(map[string]map[string][]any)
	filterMap[model.ForumPostColumns.PostAuthorID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.ForumPostColumns.ForumID] = map[string][]any{
		"equalTo": {l.svcCtx.Config.Query.PhotoForumId},
	}
	filterMap[model.ForumPostColumns.PostStatus] = map[string][]any{
		"notEqualTo": {globalkey.StatusDeleted},
	}
	selectCols := []string{
		model.ForumPostColumns.PostID,
		model.ForumPostColumns.ParentID,
		model.ForumPostColumns.PostStatus,
	}
	postList, _, err := l.svcCtx.Post.GetList(l.ctx, model.M{
		"pageSize": uint64(3),
		"orderBy":  model.ForumPostColumns.PostModifiedDate + " DESC",
		"select":   strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	photoTotal, err := l.svcCtx.Post.GetMediaCount(l.ctx, filterMap)
	if err != nil {
		return nil, err
	}

	var list []*types.PhotoPostInfo
	var publicList []*types.PhotoPostInfo

	if len(postList) > 0 {
		var ids []any
		var pids []string
		for _, v := range postList {
			ids = append(ids, v.PostID)
			pids = append(pids, strconv.FormatInt(int64(v.ParentID), 10))
		}

		mediaFilterMap := make(map[string]map[string][]any)
		mediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectID] = map[string][]any{
			"in": ids,
		}
		mediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectType] = map[string][]any{
			"equalTo": {globalkey.AttachmentLogTypeForumPost},
		}
		subSelectCols := []string{
			model.ForumAttachmentRelationshipColumns.AttachmentRelationshipID,
			model.ForumAttachmentRelationshipColumns.ObjectID,
			model.ForumAttachmentRelationshipColumns.AttachmentID,
			model.ForumAttachmentRelationshipColumns.AttachmentThumbnail,
			model.ForumAttachmentRelationshipColumns.AttachmentOrder,
			model.ForumAttachmentRelationshipColumns.AttachmentImageURL,
		}
		mediaList, _, err := l.svcCtx.Post.GetMedia(l.ctx, model.M{
			"pageSize": uint64(8),
			"orderBy":  model.ForumAttachmentRelationshipColumns.AttachmentOrder,
			"select":   strings.Join(subSelectCols, ","),
		}, -1, mediaFilterMap)
		if err != nil {
			return nil, err
		}

		idPhotoMap := make(map[uint64][]*types.MediaInfo)
		pidPhotoMap := make(map[uint64][]*types.MediaInfo)
		if len(mediaList) > 0 {
			for _, v := range mediaList {
				idPhotoMap[v.ObjectID] = append(idPhotoMap[v.ObjectID], &types.MediaInfo{
					Uid:       pointy.GetPointer(v.AttachmentRelationshipID),
					Id:        pointy.GetPointer(strconv.FormatInt(int64(v.AttachmentID), 10)),
					Url:       pointy.GetPointer(v.AttachmentImageURL),
					Thumbnail: pointy.GetPointer(v.AttachmentThumbnail > 0),
					Order:     pointy.GetPointer(uint32(v.AttachmentOrder)),
				})
			}
		}

		publicFilterMap := make(map[string]map[string][]any)
		publicFilterMap[model.ForumPostColumns.PostAuthorID] = map[string][]any{
			"equalTo": {userId},
		}
		publicFilterMap[model.ForumPostColumns.ForumID] = map[string][]any{
			"equalTo": {l.svcCtx.Config.Query.PhotoForumId},
		}
		publicFilterMap[model.ForumPostColumns.PostStatus] = map[string][]any{
			"equalTo": {globalkey.StatusApproved},
		}
		publicPostList, _, err := l.svcCtx.Post.GetList(l.ctx, model.M{
			"pageSize": uint64(3),
			"orderBy":  model.ForumPostColumns.PostModifiedDate + " DESC",
			"select":   strings.Join(selectCols, ","),
		}, -1, publicFilterMap)
		if err != nil {
			return nil, err
		}

		if len(publicPostList) > 0 {
			ids = make([]any, 0, len(publicPostList))
			for _, v := range publicPostList {
				ids = append(ids, v.PostID)
				pids = append(pids, strconv.FormatInt(int64(v.ParentID), 10))
			}

			publicMediaFilterMap := make(map[string]map[string][]any)
			publicMediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectID] = map[string][]any{
				"in": ids,
			}
			publicMediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectType] = map[string][]any{
				"equalTo": {globalkey.AttachmentLogTypeForumPost},
			}
			publicMediaList, _, err := l.svcCtx.Post.GetMedia(l.ctx, model.M{
				"pageSize": uint64(8),
				"orderBy":  model.ForumAttachmentRelationshipColumns.AttachmentOrder,
				"select":   strings.Join(subSelectCols, ","),
			}, -1, publicMediaFilterMap)
			if err != nil {
				return nil, err
			}

			if len(publicMediaList) > 0 {
				for _, v := range publicMediaList {
					pidPhotoMap[v.ObjectID] = append(pidPhotoMap[v.ObjectID], &types.MediaInfo{
						Uid:       pointy.GetPointer(v.AttachmentRelationshipID),
						Id:        pointy.GetPointer(strconv.FormatInt(int64(v.AttachmentID), 10)),
						Url:       pointy.GetPointer(v.AttachmentImageURL),
						Thumbnail: pointy.GetPointer(v.AttachmentThumbnail > 0),
						Order:     pointy.GetPointer(uint32(v.AttachmentOrder)),
					})
				}
			}
		}

		perfumeMap, err := l.getPerfumeMap(pids)
		if err != nil {
			return nil, err
		}

		if perfumeMap != nil {
			for _, v := range postList {
				if ps, ok := idPhotoMap[v.PostID]; ok {
					if pv, ok := perfumeMap[v.ParentID]; ok {
						list = append(list, &types.PhotoPostInfo{
							Id:         pointy.GetPointer(v.PostID),
							ParentId:   pointy.GetPointer(v.ParentID),
							Parent:     pv,
							Photos:     ps,
							Status:     pointy.GetPointer(uint32(v.PostStatus)),
							StatusText: pointy.GetPointer(types.GetStatusText(int32(v.PostStatus))),
						})
					}
				}
			}

			for _, v := range publicPostList {
				if ps, ok := pidPhotoMap[v.PostID]; ok {
					if pv, ok := perfumeMap[v.ParentID]; ok {
						publicList = append(publicList, &types.PhotoPostInfo{
							Id:       pointy.GetPointer(v.PostID),
							ParentId: pointy.GetPointer(v.ParentID),
							Parent:   pv,
							Photos:   ps,
						})
					}
				}
			}
		}
	}

	photoPostItems, err := json.Marshal(list)
	if err != nil {
		logrus.Info(fmt.Sprintf("RefreshCache refreshPhotoCache photoPostItems json.Marshal err: %+v", err))
		return nil, err
	}

	photoPostPublicItems, err := json.Marshal(publicList)
	if err != nil {
		logrus.Info(fmt.Sprintf("RefreshCache refreshPhotoCache json.Marshal err: %+v", err))
		return nil, err
	}

	var userMeta []*userclient.UserMetaInfo
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserStatisticForumPhotoNew), // "_photo_new_status"
		Value: pointy.GetPointer("1"),
	})
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserStatisticForumPhotoCount), // "_post_photo_count"
		Value: pointy.GetPointer(strconv.FormatInt(photoTotal, 10)),
	})
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserCacheForumPhoto), // "_photo_post_items"
		Value: pointy.GetPointer(string(photoPostItems)),
	})
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserCacheForumPhotoPublic), // "_photo_post_public_items"
		Value: pointy.GetPointer(string(photoPostPublicItems)),
	})
	_, err = l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
		UserId:   pointy.GetPointer(uint64(userId)),
		UserMeta: userMeta,
	})
	if err != nil {
		logrus.Info(fmt.Sprintf("RefreshCache refreshPhotoCache UserRpc.SetUserMeta err: %+v", err))
		return nil, err
	}

	meta = append(meta, &forum.MetaInfo{
		Id:    pointy.GetPointer(userId),
		Key:   pointy.GetPointer("photoPostItems"),
		Value: pointy.GetPointer(string(photoPostItems)),
	})
	meta = append(meta, &forum.MetaInfo{
		Id:    pointy.GetPointer(userId),
		Key:   pointy.GetPointer("photoPostPublicItems"),
		Value: pointy.GetPointer(string(photoPostPublicItems)),
	})

	return
}

func (l *RefreshCacheLogic) refreshReviewCache(in *forum.RefreshCacheReq) (meta []*forum.MetaInfo, err error) {
	userId := *in.UserId
	filterMap := make(map[string]map[string][]any)
	filterMap[model.ForumPostColumns.PostAuthorID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.ForumPostColumns.ForumID] = map[string][]any{
		"equalTo": {l.svcCtx.Config.Query.PostForumId},
	}
	filterMap[model.ForumPostColumns.PostStatus] = map[string][]any{
		"notEqualTo": {globalkey.StatusDeleted},
	}
	selectCols := []string{
		model.ForumPostColumns.PostID,
		model.ForumPostColumns.ParentID,
		model.ForumPostColumns.PostStatus,
		model.ForumPostColumns.AverageRating,
	}
	postList, _, err := l.svcCtx.Post.GetList(l.ctx, model.M{
		"pageSize": uint64(2),
		"orderBy":  model.ForumPostColumns.PostModifiedDate + " DESC",
		"select":   strings.Join(selectCols, ","),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	var list []*types.PostInfo
	var publicList []*types.PostInfo

	if len(postList) > 0 {
		var pids []string
		for _, v := range postList {
			pids = append(pids, strconv.FormatInt(int64(v.ParentID), 10))
		}

		publicFilterMap := make(map[string]map[string][]any)
		publicFilterMap[model.ForumPostColumns.PostAuthorID] = map[string][]any{
			"equalTo": {userId},
		}
		publicFilterMap[model.ForumPostColumns.ForumID] = map[string][]any{
			"equalTo": {l.svcCtx.Config.Query.PostForumId},
		}
		publicFilterMap[model.ForumPostColumns.PostStatus] = map[string][]any{
			"equalTo": {globalkey.StatusApproved},
		}
		publicPostList, _, err := l.svcCtx.Post.GetList(l.ctx, model.M{
			"pageSize": uint64(2),
			"orderBy":  model.ForumPostColumns.PostModifiedDate + " DESC",
			"select":   strings.Join(selectCols, ","),
		}, -1, publicFilterMap)
		if err != nil {
			return nil, err
		}

		if len(publicPostList) > 0 {
			for _, v := range publicPostList {
				pids = append(pids, strconv.FormatInt(int64(v.ParentID), 10))
			}
		}

		if len(pids) > 0 {
			perfumeMap, err := l.getPerfumeMap(pids)
			if err != nil {
				return nil, err
			}

			if perfumeMap != nil {
				for _, v := range postList {
					if pv, ok := perfumeMap[v.ParentID]; ok {
						list = append(list, &types.PostInfo{
							Id:         pointy.GetPointer(v.PostID),
							ParentId:   pointy.GetPointer(v.ParentID),
							Parent:     pv,
							Grade:      pointy.GetPointer(moneyx.ParseStar(v.AverageRating, 1)),
							Status:     pointy.GetPointer(uint32(v.PostStatus)),
							StatusText: pointy.GetPointer(types.GetStatusText(int32(v.PostStatus))),
						})
					}
				}

				for _, v := range publicPostList {
					if pv, ok := perfumeMap[v.ParentID]; ok {
						publicList = append(publicList, &types.PostInfo{
							Id:         pointy.GetPointer(v.PostID),
							ParentId:   pointy.GetPointer(v.ParentID),
							Parent:     pv,
							Grade:      pointy.GetPointer(moneyx.ParseStar(v.AverageRating, 1)),
							Status:     pointy.GetPointer(uint32(v.PostStatus)),
							StatusText: pointy.GetPointer(types.GetStatusText(int32(v.PostStatus))),
						})
					}
				}
			}
		}
	}

	reviewItems, err := json.Marshal(list)
	if err != nil {
		logrus.Info(fmt.Sprintf("RefreshCache refreshReviewCache reviewItems json.Marshal err: %+v", err))
		return nil, err
	}

	reviewPublicItems, err := json.Marshal(publicList)
	if err != nil {
		logrus.Info(fmt.Sprintf("RefreshCache refreshReviewCache json.Marshal err: %+v", err))
		return nil, err
	}

	var userMeta []*userclient.UserMetaInfo
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserStatisticForumReviewNew), // "_review_new_status"
		Value: pointy.GetPointer("1"),
	})
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserCacheForumReview), // "_review_items"
		Value: pointy.GetPointer(string(reviewItems)),
	})
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserCacheForumReviewPublic), // "_review_public_items"
		Value: pointy.GetPointer(string(reviewPublicItems)),
	})
	_, err = l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
		UserId:   pointy.GetPointer(uint64(userId)),
		UserMeta: userMeta,
	})
	if err != nil {
		logrus.Info(fmt.Sprintf("RefreshCache refreshReviewCache UserRpc.SetUserMeta err: %+v", err))
		return nil, err
	}

	meta = append(meta, &forum.MetaInfo{
		Id:    pointy.GetPointer(userId),
		Key:   pointy.GetPointer("reviewItems"),
		Value: pointy.GetPointer(string(reviewItems)),
	})
	meta = append(meta, &forum.MetaInfo{
		Id:    pointy.GetPointer(userId),
		Key:   pointy.GetPointer("reviewPublicItems"),
		Value: pointy.GetPointer(string(reviewPublicItems)),
	})

	return
}

func (l *RefreshCacheLogic) getPerfumeMap(ids []string) (map[uint64]*types.KbEntryInfo, error) {
	if len(ids) == 0 {
		return nil, nil
	}

	res, err := l.svcCtx.BlogRpc.BookList(l.ctx, &blogclient.BookListReq{
		Preload:   "blogBook:Id,Title,Slug;blogMedia:Id,Uid,Url,Thumbnail,Order;blogBookRelation:brand",
		EagerLoad: "blogBook:blogMedia,blogBookRelation",
		EntryIds:  strings.Join(ids, ","),
	})
	if err != nil {
		return nil, err
	}

	if len(res.Data) > 0 {
		resp := make(map[uint64]*types.KbEntryInfo)
		for _, v := range res.Data {
			var media []*types.MediaInfo
			if len(v.Media) > 0 {
				for _, m := range v.Media {
					media = append(media, &types.MediaInfo{
						Uid:       pointy.GetPointer(uint64(m.Uid)),
						Id:        pointy.GetPointer(strconv.FormatInt(int64(m.Id), 10)),
						Url:       pointy.GetPointer(m.Url),
						Thumbnail: pointy.GetPointer(m.Thumbnail > 0),
						Order:     pointy.GetPointer(uint32(m.Order)),
					})
				}
			}

			var brand []*types.KbEntryInfo
			if len(v.Relations) > 0 {
				for _, r := range v.Relations {
					if r.Section == "brand" {
						brand = append(brand, &types.KbEntryInfo{
							Id:    pointy.GetPointer(uint64(r.Id)),
							Title: pointy.GetPointer(r.Title),
							Slug:  pointy.GetPointer(r.Slug),
						})
					}
				}
			}
			resp[uint64(v.Id)] = &types.KbEntryInfo{
				Id:    pointy.GetPointer(uint64(v.Id)),
				Title: pointy.GetPointer(v.Title),
				Slug:  pointy.GetPointer(v.Slug),
				Media: media,
				Brand: brand,
			}
		}

		return resp, nil
	}

	return nil, nil
}
